<?php
/**
 * Created by PhpStorm.
 * User: whwyy
 * Date: 2018/3/26 0026
 * Time: 10:23
 */

namespace wchat\common;

use Kiri\Client;

abstract class Multiprogramming implements Progaram
{
    protected static ?Multiprogramming $instance = null;

    protected int    $errorCode = 0;
    protected string $errorMsg  = '';


    /**
     * @var AppConfig
     */
    protected AppConfig $payConfig;


    /**
     * @param $message
     * @param int $code
     * @return Result
     */
    protected function sendError($message, int $code = 500): Result
    {
        return new Result(code: $code, message: $message);
    }

    /**
     * @param $code
     */
    public function setErrorCode($code): void
    {
        $this->errorCode = $code;
    }

    /**
     * @param $message
     */
    public function setErrorMessage($message): void
    {
        $this->errorMsg = $message;
    }

    /**
     * @return int
     */
    public function getErrorCode(): int
    {
        return $this->errorCode;
    }

    /**
     * @return string
     */
    public function getErrorMessage(): string
    {
        return $this->errorMsg;
    }

    /**
     * @return AppConfig
     */
    public function getPayConfig(): AppConfig
    {
        return $this->payConfig;
    }

    /**
     * @param AppConfig $payConfig
     */
    public function setPayConfig(AppConfig $payConfig): void
    {
        $this->payConfig = $payConfig;
    }


    /**
     * @param string $host
     * @param string $requestUrl
     * @param mixed $body
     * @param string $contentType
     * @return Result
     */
    protected function post(string $host, string $requestUrl, mixed $body, string $contentType = 'application/application'): Result
    {
        return $this->request($host, 'post', $requestUrl, $body, $contentType);
    }


    /**
     * @param string $host
     * @param string $requestUrl
     * @param mixed $body
     * @param string $contentType
     * @return Result
     */
    protected function get(string $host, string $requestUrl, mixed $body, string $contentType = 'application/application'): Result
    {
        return $this->request($host, 'get', $requestUrl, $body, $contentType);
    }


    /**
     * @param string $host
     * @param string $requestUrl
     * @param mixed $body
     * @return Result
     */
    protected function upload(string $host, string $requestUrl, mixed $body): Result
    {
        return $this->request($host, 'upload', $requestUrl, $body);
    }


    /**
     * @param string $host
     * @param string $method
     * @param string $requestUrl
     * @param $body
     * @param string $contentType
     * @return Result
     */
    private function request(string $host, string $method, string $requestUrl, $body, string $contentType = 'application/application'): Result
    {
        $client    = new Client($host, 80, true);
        $proxyHost = $this->payConfig->getProxyHost();
        $proxyPort = $this->payConfig->getProxyPort();
        if (!empty($proxyHost) && $proxyPort > 0) {
            $client->withProxyHost($proxyHost)->withProxyPort($proxyPort);
        }
        if ($method == 'post') {
            $client->withHeader(['Content-Type' => $contentType]);
            $client->post($requestUrl, $body);
        } else if ($method == 'upload') {
            $client->upload($requestUrl, $body);
        } else {
            $client->withHeader(['Content-Type' => $contentType]);
            $client->get($requestUrl, $body);
        }
        $client->close();
        if (!in_array($client->getStatusCode(), [101, 200, 201])) {
            return new Result(code: 505, message: $client->getBody());
        }
        $body = json_decode($client->getBody(), true);
        if (is_null($body) || (isset($body['errcode']) && $body['errcode'] != 0)) {
            return new Result(code: $body['errcode'], message: $body['errmsg']);
        } else {
            return new Result(code: 0, data: $body);
        }
    }

}
